var StefanStorage = StefanStorage || {};

(function() {
	var defaultOptions = { fieldIdentifier: "id", fieldChilds: "children" };
	
	/**
	 * 构造函数
	 * @param {Object} data 结构化数据
	 * @param {Object} options 参数选项
	 * @class
	 */
	function StefanNode(data, options) {
		
		this.options = options || {};
		
		this.data = data;
		
		for(var i in defaultOptions) {
			!this.options[i] && (this.options[i] = defaultOptions[i]);
		}
		
		this.firstChild = null;
		
		this.lastChild = null;
		
		this.previousSibling = null;
		
		this.nextSibling = null;
		
		this.childNodes = [];
		
		this._initAllNodes(data);
	}
	
	/**
	 * 初始化所有节点/后代节点
	 * @param {Object} data 传入的结构化数据 
	 */
	StefanNode.prototype._initAllNodes = function(data) {
		var childNodes, maxi, i = 0;
		if(data && (childNodes = data[this.options.fieldChilds]) && childNodes instanceof Array) {
			for(maxi = childNodes.length; i < maxi; i++) {
				if(childNodes[i] instanceof StefanNode) {
					this.appendChild(childNodes[i]);
				}
				else {
					try {
						this.appendChild(new StefanNode(childNodes[i], this.options, this));
					}
					catch(e) {
						//do Nothing...
					}
				}
			}
		}
		if(!this.childNodes.indexOf){
	        this.childNodes.indexOf = function(o){
	            for(var i = 0, maxi = this.length; i < maxi; i++){
	                if(this[i] == o){
	                    return i;
	                }
	            }
	            return -1;
	        };
	    }
	}
	
	/**
	 * 剔除一个子节点，但不销毁它
	 * @param {StefanNode} node 被剔除的子节点
	 */
	StefanNode.prototype._kickChild = function(node) {
		var index = this.childNodes.indexOf(node);
        if(index == -1) return false;

        this.childNodes.splice(index, 1);

        //更新兄弟节点
        if(node.previousSibling) node.previousSibling.nextSibling = node.nextSibling;
        if(node.nextSibling) node.nextSibling.previousSibling = node.previousSibling;

        //更新第一个/最后一个节点
        if(this.firstChild == node) this.firstChild = node.nextSibling;
        if(this.lastChild == node) this.lastChild = node.previousSibling;
		
		return node;
	}
	
	/**
	 * 销毁自己，释放内存
	 */
	StefanNode.prototype.destory = function(){
        this.parentNode = this.previousSibling = this.nextSibling = this.firstChild = this.lastChild = null;
        this.childNodes = null;
		return this;
    },
	
	/**
	 * 插入一个节点（可以完成移动的动能）
	 * @param {StefanNode} node 源界节点
	 * @param {StefanNode} tNode 目标节点
	 */
	StefanNode.prototype.insertBefore = function(node, tNode){
        if(!tNode) return this.appendChild(node);
		
		if(!node instanceof StefanNode) {
			if(typeof StefanNode !== "object") return;
			node = new StefanNode(node, this.options);
		}
		
        var index = this.childNodes.indexOf(tNode),
        	oldParent = node.parentNode,
        	tIndex = index;

        //源节点和目标节点都是本节点的子节点
        if(oldParent == this && this.childNodes.indexOf(node) < index) tIndex--;

        //维护引用关系
        if(oldParent) oldParent._kickChild(node);
        if(tIndex === 0) this.firstChild = node;
		
        this.childNodes.splice(tIndex, 0, node);
        node.parentNode = this;
		
        var ps = this.childNodes[tIndex-1];
        if(ps){
            node.previousSibling = ps;
            ps.nextSibling = node;
        }else node.previousSibling = null;
		
        node.nextSibling = tNode;
        tNode.previousSibling = node;
		
        return node;
    }
	
	/**
	 * 删除所有子节点
	 */
	StefanNode.prototype.removeAll = function() {
		var cn = this.childNodes, n;
		while(n = cn[0]) {
			this.removeChild(n);
		}
	};
	
	/**
	 * 删除一个节点本身
	 * @return {StefanNode} 返回删除的节点
	 */
	StefanNode.prototype.remove = function() {
		if(this.parentNode) this.parentNode.removeChild(this);
		return this;
	};
	
	/**
	 * 删除一个子节点
	 * @param {StefanNode} node 被删除的节点
	 */
	StefanNode.prototype.removeChild = function(node){
		return (node = this._kickChild(node)) && node.destory();
    };
	
	/**
     * 在子节点的最后添加一个子节点
     * @param {Node/Array} 子节点、子节点数组或者子节点的枚举
     * @return 添加的节点
     */
	StefanNode.prototype.appendChild = function(node) {
		var nodesArr = false;
        if(node instanceof Array){
            nodesArr = node;
        }else if(arguments.length > 1){
            nodesArr = arguments;
        }
        if(nodesArr){
            for(var i = 0, maxi = nodesArr.length; i < maxi; i++) this.appendChild(nodesArr[i]);
        }else{
			if(!node instanceof StefanNode) {
				if(typeof StefanNode !== "object") return;
				node = new StefanNode(node, this.options);
			}
            var pos = this.childNodes.length,
            	oldParent = node.parentNode;
			//从原来的父节点中移除该节点、方便拖拽时的数据维护
            if(oldParent) oldParent._kickChild(node);
			
            pos = this.childNodes.length;
            if(pos === 0) this.firstChild = node;
            this.childNodes.push(node);
            node.parentNode = this;
            var ps = this.childNodes[pos-1];
			
			//维护兄弟节点
            if(ps){
                node.previousSibling = ps;
                ps.nextSibling = node;
            }else node.previousSibling = null;
			
            node.nextSibling = null;
            this.lastChild = node;
			return node;
        }
	};
	
	/**
	 * 判断是否有子节点
	 */
	StefanNode.prototype.hasChildNodes = function() {
		return !!this.childNodes.length;
	};
	
	/**
     * 遍历子节点的方法
     * @param {Function} fn 回调函数，返回false则中止遍历
     * @param {Boolean} deep 是否深度遍历
     */
	StefanNode.prototype.eachChild = function(fn, deep){
        var cs = this.childNodes;
        for(var i = 0, length = cs.length; i < length; i++) {
            if(fn.apply(cs[i], [cs[i]]) === false) return false;
			else if(deep) if(cs[i].eachChild(fn, deep) === false) return false;
        }
    };
	
	/**
     * 查找子节点的方法
     * @param {Function} fn 回调函数，返回false则中止遍历
     * @param {Boolean} deep 是否深度遍历
     */
	StefanNode.prototype.findChild = function(fn, deep) {
        var cs = this.childNodes, length = cs.length, i = 0,
            n = null, res;
        for(; i < length; i++){
            n = cs[i];
            if(fn.call(n, n) === true) return n;
            else if (deep){
                res = n.findChild(fn, deep);
                if(res != null) return res;
            }
        }
    },
	
	/**
     * 返回节点深度
     * @return {Number}
     */
    StefanNode.prototype.getDepth = function(){
        var depth = 0, p = this;
        while(p.parentNode){
            ++depth;
            p = p.parentNode;
        }
        return depth;
    },
	
	/**
     * 根据指定的方法排序子节点
     * @param {Function} fn 排序方法
     * @param {Boolean} deep 是否深度遍历
     */
    StefanNode.prototype.sort = function(fn, deep){
        var cs = this.childNodes, length = cs.length;
        if(length > 0){
            var i = 0;
            cs.sort(fn);
            for(; i < length; i++){
                var n = cs[i];
                n.previousSibling = cs[i-1];
                n.nextSibling = cs[i+1];
                if(i === 0) this.firstChild = n;
                if(i == length - 1) this.lastChild = n;
				if(deep) cs[i].sort(fn, deep);
            }
        }
    },
	
	/**
     * 判断该节点是否为传入节点的祖先
     * @param {StefanNode} node 判断的节点
     * @return {Boolean} 是否是祖先
     */
    StefanNode.prototype.isAncestor = function(node){
        var pn = this.parentNode;
        while(pn){
            if(pn == node) return true;
            pn = pn.parentNode;
        }
        return false;
    };

	/**
	 * 创建一个节点
	 * @param {Object} data 数据项
	 * @param {Object} options 配置项
	 * 	{String} fieldIdentifier 标识符字段，默认为："id"
	 *  {String} fieldChilds 子节点字段，默认为："nodes"
	 */
	StefanStorage.createNode = function(data, options) {
		data = data || {};
		return new StefanNode(data, options);
	};
})();
